#include "gnss.h"

#include "media.h"
#include "utc_timer.h"
#include "api_hal_gpio.h"
#include "api_fs.h"
#include "api_charset.h"

// GNSS原始输出日志
static const char TfGnssLogFileName[] = "/t/GPS_Original_Log.csv";

static GnssNmea_t gnssNema = {0};
static uint8_t SetTimeFlag = 0;

// Nmea 消息接收
static void gnssEventNmeaReveived(GnssEvent_t* pEvent)
{
    GnssNmea_t* nmea = (GnssNmea_t*)pEvent->EventData;

    if (nmea != NULL)
    {
        MediaEvent_t* mediaEvent = (MediaEvent_t*)OS_Malloc(sizeof(MediaEvent_t)); // 给事件接收方释放内存
        char *buff= (char *)OS_Malloc(128);                                         // 给事件接收方释放内存

        gnssNema = *nmea;

        if (buff)
        {
            TIME_System_t calendar;
            memset(buff, 0, 128);

            RTC_MakeCalendar(StampType2000, nmea->genTime, &calendar);

            // 定位校时逻辑
            if (nmea->IsVaild && SetTimeFlag < 3) // 定位有效设置时间
            {
                SetTimeFlag++;

                if (SetTimeFlag >= 3)
                    TIME_SetLocalTime(&calendar);
            }
            else if (nmea->IsVaild == 0)
                SetTimeFlag = 0;

            //                  Date                            AV   FIX  GN   GP   BD   Lat       Lon       Alt   Spd
            snprintf(buff, 128, "%4d-%02d-%02d %02d:%02d:%02d, %2d, %2d, %2d, %2d, %2d, %3d.%-6d, %4d.%-6d, %-5d, %d.%d\r\n", 
                calendar.year, calendar.month,  calendar.day,
                calendar.hour, calendar.minute, calendar.second,
                nmea->IsVaild, nmea->FixQuality, nmea->GnssTracked, nmea->GpsTracked, nmea->BdsTracked,
                nmea->Latitude / 1000000,  nmea->Latitude % 1000000,
                nmea->Longitude / 1000000, nmea->Longitude % 1000000,
                nmea->Altitude, nmea->Speed / 10, nmea->Speed % 10);
            
            mediaEvent->EventId   = kMediaEventGnssData;
            mediaEvent->EventData = (void *)buff;

            OS_SendEvent(MediaTaskHandle, mediaEvent, OS_TIME_OUT_WAIT_FOREVER, OS_EVENT_PRI_NORMAL);
        }
    }
}

// 事件处理
static void gnssEventDispatch(GnssEvent_t* pEvent)
{
    switch(pEvent->EventId)
    {
        case kGnssEventNmeaReveived:
            gnssEventNmeaReveived(pEvent);
            break;
        default:
            break;
    }
}

static bool CreateGnssLogFile(void)
{
    int32_t  fd;
    int32_t  ret;
    uint8_t* path = (uint8_t*)TfGnssLogFileName;
    uint8_t  buffer[128] = {0};

    // 文件不存在就创建文件，写入标题头
    fd = API_FS_Open(path, FS_O_RDONLY, 0);
    if (fd < 0)
        return false;

    fd = API_FS_Open(path, FS_O_RDWR | FS_O_CREAT, 0);
    if ( fd < 0)
        return false;    

    snprintf((char *)buffer, 128,
            "Time, IsVailed, FixQuality, GnssTracked, GpsTracked, BdsTracked, Latitude, Longitude, Altitude, Speed");

    buffer[126] = '\r'; buffer[127] = '\n';
    
    ret = API_FS_Write(fd, (uint8_t*)buffer, strlen(buffer));
    API_FS_Close(fd); // 无论如何先关了再说

    if(ret <= 0)
        return false;

    return true;  
}

GnssNmea_t* gnss_GetInfo(void)
{
    return &gnssNema;
}

// 主任务 派发事件
void Gnss_TaskEntry(void *pData)
{
    GPS_Info_t*  gpsInfo = Gps_GetInfo();
    GnssEvent_t* event = NULL;

    GPS_Init();
    GPS_Open(NULL);

    // 等待GPS启动
    while(gpsInfo->rmc.latitude.value == 0)
        OS_Sleep(1000);

    // set gps nmea output interval 方便后面设置
    for (uint8_t i = 0; i < 3; i++) {
        bool ret = GPS_SetOutputInterval(10000);

        if (ret) break;

        OS_Sleep(1000);
    }

    // 清除GPS flash数据
    //GPS_ClearInfoInFlash();
    // 搜星模式       gps glonass beidou galieo
    GPS_SetSearchMode(true, false, true, false);

    CreateGnssLogFile();

    // set gps nmea output interval 还原
    for (uint8_t i = 0; i < 3; i++) {
        bool ret = GPS_SetOutputInterval(1000);

        if (ret) break;

        OS_Sleep(1000);
    }

    //Wait event
    while (1) {
        if (OS_WaitEvent(GnssTaskHandle, (void**)&event, OS_TIME_OUT_WAIT_FOREVER)) {
            gnssEventDispatch(event);
            OS_Free(event->EventData);
            OS_Free(event);
        }

        OS_Sleep(200);
    }
}

